package filter

import (
	"math"

	"file_explorer/common/util"
	"file_explorer/model"
	"file_explorer/view/store"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
)

type MaxSizeFilter struct {
	content *fyne.Container
	limit   *FileSizeLimit
}

func (filter *MaxSizeFilter) GetCanvasObject() fyne.CanvasObject {
	return filter.content
}

func (filter *MaxSizeFilter) Filter(fileInfo *model.FileInfo) bool {
	if len(filter.limit.entry.Text) == 0 {
		return true
	}

	size := float64(fileInfo.Size)
	if fileInfo.IsDir() {
		size = 0
	}
	limit := filter.limit.slider.Value * float64(filter.limit.maxSize)
	return size <= limit
}

func (filter *MaxSizeFilter) GetValue() string {
	return filter.limit.entry.Text
}

func (filter *MaxSizeFilter) LoadValue(val string) {
	filter.limit.entry.Text = val
	filter.limit.entry.Refresh()

	filter.limit.updateSliderByEntry()
}

func (filter *MaxSizeFilter) Reset() {
	filter.limit.entry.Text = ""
	filter.limit.slider.Value = 1
	filter.limit.entry.Refresh()
	filter.limit.slider.Refresh()
	filter.limit.refreshMaxSize()
}

func NewMaxSizeFilter(tabCtx *store.FileTabContext, onChange func()) *MaxSizeFilter {
	filter := &MaxSizeFilter{
		limit: newFileSizeLimit(tabCtx, onChange, 1, "max size"),
	}

	filter.content = container.NewVBox(filter.limit.entry, filter.limit.slider)

	return filter
}

type FileSizeLimit struct {
	entry   *widget.Entry
	slider  *widget.Slider
	maxSize int64
	tabCtx  *store.FileTabContext
}

func (limit *FileSizeLimit) refreshMaxSize() {
	limit.maxSize = int64(0)
	for _, fileInfo := range limit.tabCtx.FileInfos {
		if !fileInfo.IsDir() {
			limit.maxSize = max(limit.maxSize, fileInfo.Size)
		}
	}
}

func (limit *FileSizeLimit) updateSliderByEntry() bool {
	size, _ := util.ParseSize(limit.entry.Text)
	sliderVal := float64(size) / float64(limit.maxSize)
	if math.Abs(limit.slider.Value-sliderVal) > 0.01 {
		limit.slider.SetValue(sliderVal)
		limit.slider.Refresh()
		return true
	}
	return false
}

func (limit *FileSizeLimit) updateEntryBySlider() bool {
	percentage := limit.slider.Value
	entryText := util.ConvSize(int64(float64(limit.maxSize) * percentage))
	if limit.entry.Text != entryText {
		limit.entry.SetText(entryText)
		limit.entry.Refresh()
		return true
	}
	return false
}

func newFileSizeLimit(tabCtx *store.FileTabContext, onChange func(), percentage float64, placeholder string) *FileSizeLimit {
	limit := &FileSizeLimit{
		tabCtx: tabCtx,
		slider: widget.NewSlider(0, 1),
		entry:  widget.NewEntry(),
	}

	limit.refreshMaxSize()

	limit.slider.Step = 0.01
	limit.slider.Value = percentage
	// slider更新时同步到entry
	limit.slider.OnChanged = func(p float64) {
		if limit.updateEntryBySlider() {
			onChange()
		}
	}

	limit.entry.PlaceHolder = placeholder
	limit.entry.Validator = func(s string) error {
		_, err := util.ParseSize(s)
		return err
	}
	// entry提交时同步到slider
	limit.entry.OnSubmitted = func(s string) {
		limit.updateSliderByEntry()
	}

	return limit
}
